using Sage.Http.Utilities;
using System.Diagnostics.CodeAnalysis;
using System.Net.Http.Headers;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;

namespace Sage.Http.Extensions
{
    /// <summary>
    /// 为HttpClient提供流式操作功能的扩展方法
    /// </summary>
    public static class HttpStreamingExtensions
    {
        /// <summary>
        /// 获取流式响应并逐行处理JSON数据
        /// </summary>
        /// <typeparam name="T">响应项类型</typeparam>
        /// <param name="client">HTTP客户端</param>
        /// <param name="requestUri">请求URI</param>
        /// <param name="deserializer">自定义反序列化函数，如果为null则自动创建</param>
        /// <param name="jsonTypeInfo">JSON类型信息，用于AOT环境（推荐）</param>
        /// <param name="jsonOptions">自定义JSON序列化选项</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>响应项的异步枚举器</returns>
        /// <remarks>
        /// 此方法适用于Server-Sent Events (SSE)或其他流式JSON响应。
        /// 每行应包含一个完整的JSON对象。
        /// 
        /// 在AOT环境中，建议提供jsonTypeInfo参数以启用源生成序列化。
        /// </remarks>
        [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
        [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation.")]
        public static async IAsyncEnumerable<T> GetStreamingAsync<T>(
            this HttpClient client,
            string requestUri,
            Func<string, T>? deserializer = null,
            JsonTypeInfo<T>? jsonTypeInfo = null,
            JsonSerializerOptions? jsonOptions = null,
            [EnumeratorCancellation] CancellationToken cancellationToken = default)
        {
            ArgumentNullException.ThrowIfNull(client);
            ArgumentException.ThrowIfNullOrEmpty(requestUri);

            HttpResponseMessage? response = null;
            Stream? stream = null;
            StreamReader? reader = null;

            try
            {
                var request = new HttpRequestMessage(HttpMethod.Get, requestUri);

                // 添加适合流式响应的头
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream"));

                // 使用ResponseHeadersRead选项，以便在接收到头信息后就返回响应
                response = await client.SendAsync(
                    request,
                    HttpCompletionOption.ResponseHeadersRead,
                    cancellationToken).ConfigureAwait(false);

                response.EnsureSuccessStatusCode();

                // 创建反序列化函数
                deserializer ??= JsonSerializerUtilities.CreateDeserializer(jsonTypeInfo, jsonOptions);

                stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                reader = new StreamReader(stream);

                string? line;
                while ((line = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false)) != null)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    // 跳过空行
                    if (string.IsNullOrWhiteSpace(line))
                        continue;

                    // 提取并处理数据行
                    string dataContent = ExtractDataContent(line);
                    if (string.IsNullOrEmpty(dataContent))
                        continue;

                    // 处理数据行
                    if (JsonSerializerUtilities.TryDeserialize(dataContent, deserializer, out T? item) &&
                        item is not null)
                    {
                        yield return item;
                    }
                }
            }
            finally
            {
                // 按照创建的相反顺序释放资源
                // 优先使用异步释放（如果支持）
                if (reader is IAsyncDisposable asyncReader)
                    await asyncReader.DisposeAsync().ConfigureAwait(false);
                else
                    reader?.Dispose();

                if (stream is IAsyncDisposable asyncStream)
                    await asyncStream.DisposeAsync().ConfigureAwait(false);
                else
                    stream?.Dispose();

                if (response is IAsyncDisposable asyncResponse)
                    await asyncResponse.DisposeAsync().ConfigureAwait(false);
                else
                    response?.Dispose();
            }
        }

        /// <summary>
        /// 处理流式响应并通过回调函数处理每一行
        /// </summary>
        /// <param name="client">HTTP客户端</param>
        /// <param name="requestUri">请求URI</param>
        /// <param name="lineProcessor">行处理回调函数</param>
        /// <param name="isEventStream">是否为Server-Sent Events流</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>处理的总行数</returns>
        public static async Task<int> ProcessStreamAsync(
            this HttpClient client,
            string requestUri,
            Func<string, Task> lineProcessor,
            bool isEventStream = false,
            CancellationToken cancellationToken = default)
        {
            ArgumentNullException.ThrowIfNull(client);
            ArgumentException.ThrowIfNullOrEmpty(requestUri);
            ArgumentNullException.ThrowIfNull(lineProcessor);

            var request = new HttpRequestMessage(HttpMethod.Get, requestUri);

            // 添加适合流式响应的头
            if (isEventStream)
            {
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream"));
            }

            // 使用ResponseHeadersRead选项，以便在接收到头信息后就返回响应
            using var response = await client.SendAsync(
                request,
                HttpCompletionOption.ResponseHeadersRead,
                cancellationToken).ConfigureAwait(false);

            response.EnsureSuccessStatusCode();

            using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
            using var reader = new StreamReader(stream);

            int lineCount = 0;
            string? line;
            while ((line = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false)) != null)
            {
                cancellationToken.ThrowIfCancellationRequested();

                // 跳过空行
                if (string.IsNullOrWhiteSpace(line))
                    continue;

                // 处理数据行
                string dataContent;
                if (isEventStream && line.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
                {
                    dataContent = line[5..].Trim();
                    if (string.IsNullOrEmpty(dataContent))
                        continue;
                }
                else
                {
                    dataContent = line;
                }

                await lineProcessor(dataContent).ConfigureAwait(false);
                lineCount++;
            }

            return lineCount;
        }

        /// <summary>
        /// 发送POST请求并获取流式响应
        /// </summary>
        /// <typeparam name="T">响应项类型</typeparam>
        /// <param name="client">HTTP客户端</param>
        /// <param name="requestUri">请求URI</param>
        /// <param name="content">请求内容</param>
        /// <param name="deserializer">自定义反序列化函数，如果为null则自动创建</param>
        /// <param name="jsonTypeInfo">JSON类型信息，用于AOT环境（推荐）</param>
        /// <param name="jsonOptions">自定义JSON序列化选项</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>响应项的异步枚举器</returns>
        /// <remarks>
        /// 此方法特别适用于需要发送请求体的流式API，如ChatGPT等AI模型的流式响应。
        /// 
        /// 在AOT环境中，建议提供jsonTypeInfo参数以启用源生成序列化。
        /// </remarks>
        [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
        [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation.")]
        public static async IAsyncEnumerable<T> PostStreamingAsync<T>(
            this HttpClient client,
            string requestUri,
            HttpContent content,
            Func<string, T>? deserializer = null,
            JsonTypeInfo<T>? jsonTypeInfo = null,
            JsonSerializerOptions? jsonOptions = null,
            [EnumeratorCancellation] CancellationToken cancellationToken = default)
        {
            ArgumentNullException.ThrowIfNull(client);
            ArgumentException.ThrowIfNullOrEmpty(requestUri);
            ArgumentNullException.ThrowIfNull(content);

            HttpResponseMessage? response = null;
            Stream? stream = null;
            StreamReader? reader = null;

            try
            {
                var request = new HttpRequestMessage(HttpMethod.Post, requestUri)
                {
                    Content = content
                };

                // 添加适合流式响应的头
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream"));

                // 使用ResponseHeadersRead选项，以便在接收到头信息后就返回响应
                response = await client.SendAsync(
                    request,
                    HttpCompletionOption.ResponseHeadersRead,
                    cancellationToken).ConfigureAwait(false);

                response.EnsureSuccessStatusCode();

                // 创建反序列化函数
                deserializer ??= JsonSerializerUtilities.CreateDeserializer(jsonTypeInfo, jsonOptions);

                stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                reader = new StreamReader(stream);

                string? line;
                while ((line = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false)) != null)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    // 跳过空行
                    if (string.IsNullOrWhiteSpace(line))
                        continue;

                    // 提取并处理数据行
                    string dataContent = ExtractDataContent(line);
                    if (string.IsNullOrEmpty(dataContent))
                        continue;

                    // 处理数据行
                    if (JsonSerializerUtilities.TryDeserialize(dataContent, deserializer, out T? item) &&
                        item is not null)
                    {
                        yield return item;
                    }
                }
            }
            finally
            {
                reader?.Dispose();
                stream?.Dispose();
                response?.Dispose();
            }
        }

        /// <summary>
        /// 提取数据内容，处理SSE格式和普通文本行
        /// </summary>
        /// <param name="line">原始行文本</param>
        /// <returns>数据内容</returns>
        private static string ExtractDataContent(string line)
        {
            // 检查是否为SSE格式的数据行
            if (line.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
            {
                return line[5..].Trim();
            }

            return line;
        }
    }
}